package manager;

import java.util.Date;
import java.util.List;

import org.hibernate.Session;

import util.HibernateSessionFactory;

import model.Category;
import model.Profile;
import model.Setting;
import model.User;
import dao.ProfileDAO;
import dao.SettingDAO;
import dao.UserDAO;

/**
 * Managing User, using singleton
 * 
 * @author xbingo
 * 
 */
public class UserManager {
	private static UserDAO userDao = new UserDAO();
	private static ProfileDAO profileDao = new ProfileDAO();
	private static SettingDAO settingDao = new SettingDAO();
	private static UserManager userManager = new UserManager();
	
	
	private UserManager() {

	}

	/**
	 * 
	 * @return UserManager instance
	 */
	public static UserManager getUserManager() {
		
		return userManager;
	}
	
	
	public static UserDAO getUserDAO() {
		return userDao;
	}
	public static ProfileDAO getProfileDAO(){
		return profileDao;
	}
	public static SettingDAO getSettingDAO(){
		return settingDao;
	}
	
	/**
	 * 
	 * @return default setting
	 */
	private Setting getDefaultSetting() {
		// initialize default setting
		Setting defaultSetting = new Setting();
		defaultSetting.setCompiler(CompilerManager.getCompilerManager()
				.getDefaultCompiler());
		defaultSetting.setTheme("default");
		return defaultSetting;
	}

	/**
	 * 
	 * @param user The user to be registered.
	 * @throws UserAlreadyExistsException
	 * @return the user registered if successful. 
	 */
	public User register(User user) throws UserAlreadyExistsException {
		List<User> list = getUserDAO().findByUsername(user.getUsername());
		if (!list.isEmpty()) {
			throw new UserAlreadyExistsException();
		} else {
			Session session = HibernateSessionFactory.getSession();
			session.beginTransaction();
			
			Profile profile = new Profile();	
			profile.setUser(user);
			Setting setting = getDefaultSetting();
			
			
			user.setRegisterDate(new Date());
			user.setProfile(profile);
			user.setSetting(setting);
			user.setType("user");
			
			Category category = CategoryManager.getCategoryManager().getDefaultCategory();
			category.setUser(user);
			user.getCategories().add(category);
			
			getUserDAO().save(user);
			getSettingDAO().save(setting);
			CategoryManager.getCategoryManager().updateCategory(category);
			getProfileDAO().save(profile);
			
			session.getTransaction().commit();
		}
		return user;
	}
	
	/**
	 * Validate the user name and password,<br>
	 * then returns the user object when the validation is OK.
	 * @return the user object
	 * @throws UserNotExist
	 * @throws PasswordIncorrect
	 */
	public User login(String username,String password) 
	throws UserNotExist,PasswordIncorrect{
		User user;
		List<User> list = getUserDAO().findByUsername(username);
		if(list.size() == 0)throw new UserNotExist();
		user = list.get(0);
		
		if(user.getPassword().equals(password)) 
			return user;
		else
			throw new PasswordIncorrect();
	}
	
	/**
	 * Update the profile of user.
	 * @param user
	 */
	void updateProfile(User user){
		getProfileDAO().save(user.getProfile());
	}
	
	/**
	 * 
	 * Update the setting of user. 
	 * 
	 * @param user
	 * 
	 */
	void updateSettiong(User user){
		getSettingDAO().save(user.getSetting());
	}
}
